#include <jni.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <android/log.h>

#define LOG_TAG    "native-i2c-log"
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGW(...)  __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGV(...)  __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)


/*
 * Class:     com_unione_unione_voice_i2c_I2C
 * Method:    open
 * Signature: (Ljava/lang/String;)I
 */
extern "C" JNIEXPORT jint JNICALL
Java_com_unione_unione_1voice_i2c_I2C_open(JNIEnv *env, jobject obj, jstring str) {
    const char *nativeStr = env->GetStringUTFChars(str, nullptr);
    int fd = open(nativeStr, O_RDWR, 644);
    env->ReleaseStringUTFChars(str, nativeStr);
    LOGI("native 打开i2c");
    return fd;
}

/*
 * Class:     com_unione_unione_voice_i2c_I2C
 * Method:    read
 * Signature: (IB[BI)I
 */
extern "C" JNIEXPORT jint JNICALL
Java_com_unione_unione_1voice_i2c_I2C_read(JNIEnv *env, jobject obj, jint fd, jbyte b,
                                           jbyteArray buf, jint len) {
    struct i2c_rdwr_ioctl_data rdwr;
    struct i2c_msg msgs[1];
    int ret;
    // 获取 jbyteArray 的长度
    jsize length = (*env).GetArrayLength(buf);

    // 分配内存空间来存储 __u8 类型的数组
    unsigned char *cbuf = (unsigned char *) malloc(length * sizeof(unsigned char));
    (*env).GetByteArrayRegion(buf, 0, length, (signed char *) cbuf);
    rdwr.msgs = msgs;
    rdwr.nmsgs = 1;
    int slave = static_cast<int>(b);
    rdwr.msgs[0].addr = (slave >> 1);
    rdwr.msgs[0].flags = I2C_M_RD;
    rdwr.msgs[0].len = len;
    rdwr.msgs[0].buf = (__u8 *) cbuf;
    ret = ioctl(fd, I2C_RDWR, &rdwr);
    // 释放内存空间
    free(cbuf);
    if (ret < 0) {
        return ret;
    }
    return 0;
}

/*
 * Class:     com_unione_unione_voice_i2c_I2C
 * Method:    write
 * Signature: (IB[BI)I
 */
extern "C" JNIEXPORT jint JNICALL
Java_com_unione_unione_1voice_i2c_I2C_write(JNIEnv *env, jobject obj, jint fd, jbyte b,
                                            jbyteArray buf, jint len) {
    struct i2c_rdwr_ioctl_data rdwr;
    struct i2c_msg msgs[1];
    int ret;
    // 获取 jbyteArray 的长度
    jsize length = (*env).GetArrayLength(buf);

    // 分配内存空间来存储 __u8 类型的数组
    unsigned char *cbuf = (unsigned char *) malloc(length * sizeof(unsigned char));
    (*env).GetByteArrayRegion(buf, 0, length, (signed char *) cbuf);
    int slave = static_cast<int>(b);
    rdwr.msgs = msgs;
    rdwr.nmsgs = 1;
    rdwr.msgs[0].addr = (slave);
    rdwr.msgs[0].flags = !I2C_M_RD;
    rdwr.msgs[0].len = len;
    rdwr.msgs[0].buf = (__u8 *) cbuf;

    ret = ioctl(fd, I2C_RDWR, &rdwr);
    LOGI("native write 数据");
    free(cbuf);
    if (ret < 0) {
        return ret;
    }
    return 0;
}

/*
 * Class:     com_unione_unione_voice_i2c_I2C
 * Method:    close
 * Signature: (I)V
 */
extern "C" JNIEXPORT void JNICALL
Java_com_unione_unione_1voice_i2c_I2C_close(JNIEnv *env, jobject obj, jint fd) {
    close(fd);
}